import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Point2D;
import java.util.ArrayList;

import javax.swing.BoxLayout;


public class FunctionDisplay extends Panel {
	
	private Scroll2DGraph accFunc, velFunc, disFunc;
	private RootPanel rootPanel;
	
	public FunctionDisplay(RootPanel rootPanel) {
		this.rootPanel = rootPanel;
		this.setBackground(Color.WHITE);
		this.refreshGraphs();
		this.establishLayout();
	}
	
	public Dimension GetPerferredSize() {
		return new Dimension(500, 500);
	}
	
	public Insets getInsets() {
		return new Insets(5, 1, 1, 5);
	}
	
	private ArrayList<Point2D> buildPoints(double[] xVals, double lowerBound) {
		ArrayList<Point2D> pts = new ArrayList<Point2D>(xVals.length);
		
		double currXVal = lowerBound;
		for (int i = 0; i < xVals.length; i++) {
			pts.add(new Point2D.Double(currXVal, xVals[i]));
			currXVal += MembershipFunction.RESOLUTION;
		}
		
		return pts;
	}
	
	private void establishLayout() {
		this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
		this.add(this.accFunc);
		this.add(this.velFunc);
		this.add(this.disFunc);
	}
	
	public void refreshGraphs() {
		this.removeAll();
		
		double[] tempArray = null;
		double tempLowerBound = -1.0;
		int largestNumPts = -1;
		
		// Obtain acceleration data points
		tempArray = FuzzySetsManager.getInstance().getQualifiedConsequent(FuzzySet.A_ACCELERATE, 1.0);
		tempLowerBound = FuzzySetsManager.getInstance().getLowerBound(FuzzySet.A_ACCELERATE);
		ArrayList<Point2D> aAcceleratePts = this.buildPoints(tempArray, tempLowerBound);
		largestNumPts = aAcceleratePts.size();
		
		tempArray = FuzzySetsManager.getInstance().getQualifiedConsequent(FuzzySet.A_ACCELERATEHARD, 1.0);
		tempLowerBound = FuzzySetsManager.getInstance().getLowerBound(FuzzySet.A_ACCELERATEHARD);
		ArrayList<Point2D> aAccelHardPts = this.buildPoints(tempArray, tempLowerBound);
		largestNumPts = Math.max(aAccelHardPts.size(), largestNumPts);
		
		tempArray = FuzzySetsManager.getInstance().getQualifiedConsequent(FuzzySet.A_BRAKE, 1.0);
		tempLowerBound = FuzzySetsManager.getInstance().getLowerBound(FuzzySet.A_BRAKE);
		ArrayList<Point2D> aBrakePts = this.buildPoints(tempArray, tempLowerBound);
		largestNumPts = Math.max(aBrakePts.size(), largestNumPts);
		
		tempArray = FuzzySetsManager.getInstance().getQualifiedConsequent(FuzzySet.A_BRAKEHARD, 1.0);
		tempLowerBound = FuzzySetsManager.getInstance().getLowerBound(FuzzySet.A_BRAKEHARD);
		ArrayList<Point2D> aBrakeHardPts = this.buildPoints(tempArray, tempLowerBound);
		largestNumPts = Math.max(aBrakeHardPts.size(), largestNumPts);
		
		tempArray = FuzzySetsManager.getInstance().getQualifiedConsequent(FuzzySet.A_NONE, 1.0);
		tempLowerBound = FuzzySetsManager.getInstance().getLowerBound(FuzzySet.A_NONE);
		ArrayList<Point2D> aNonePts = this.buildPoints(tempArray, tempLowerBound);
		largestNumPts = Math.max(aNonePts.size(), largestNumPts);
		
		// Add acceleration lines
		this.accFunc  = new Scroll2DGraph("Ua", "Acceleration (m/s^2)", 0, 1, largestNumPts);
		this.accFunc.setDisplayExtraXValues(true);
		this.accFunc.addGraphDataLine("aAccelerate", Color.RED, Color.RED, aAcceleratePts);
		this.accFunc.addGraphDataLine("aAccelerateHard", Color.MAGENTA, Color.MAGENTA, aAccelHardPts);
		this.accFunc.addGraphDataLine("aBrake", Color.BLUE, Color.BLUE, aBrakePts);
		this.accFunc.addGraphDataLine("aBrakeHard", Color.YELLOW, Color.YELLOW, aBrakeHardPts);
		this.accFunc.addGraphDataLine("aNone", Color.GREEN, Color.GREEN, aNonePts);
		
		// Obtain velocity data points
		tempArray = FuzzySetsManager.getInstance().getQualifiedConsequent(FuzzySet.V_JUSTRIGHT, 1.0);
		tempLowerBound = FuzzySetsManager.getInstance().getLowerBound(FuzzySet.V_JUSTRIGHT);
		ArrayList<Point2D> vJustRightPts = this.buildPoints(tempArray, tempLowerBound);
		largestNumPts = vJustRightPts.size();
		
		tempArray = FuzzySetsManager.getInstance().getQualifiedConsequent(FuzzySet.V_FAST, 1.0);
		tempLowerBound = FuzzySetsManager.getInstance().getLowerBound(FuzzySet.V_FAST);
		ArrayList<Point2D> vFastPts = this.buildPoints(tempArray, tempLowerBound);
		largestNumPts = Math.max(vFastPts.size(), largestNumPts);
		
		tempArray = FuzzySetsManager.getInstance().getQualifiedConsequent(FuzzySet.V_VERYFAST, 1.0);
		tempLowerBound = FuzzySetsManager.getInstance().getLowerBound(FuzzySet.V_VERYFAST);
		ArrayList<Point2D> vVeryFastPts = this.buildPoints(tempArray, tempLowerBound);
		largestNumPts = Math.max(vVeryFastPts.size(), largestNumPts);
		
		tempArray = FuzzySetsManager.getInstance().getQualifiedConsequent(FuzzySet.V_SLOW, 1.0);
		tempLowerBound = FuzzySetsManager.getInstance().getLowerBound(FuzzySet.V_SLOW);
		ArrayList<Point2D> vSlowPts = this.buildPoints(tempArray, tempLowerBound);
		largestNumPts = Math.max(vSlowPts.size(), largestNumPts);
		
		tempArray = FuzzySetsManager.getInstance().getQualifiedConsequent(FuzzySet.V_VERYSLOW, 1.0);
		tempLowerBound = FuzzySetsManager.getInstance().getLowerBound(FuzzySet.V_VERYSLOW);
		ArrayList<Point2D> vVerySlowPts = this.buildPoints(tempArray, tempLowerBound);
		largestNumPts = Math.max(vVerySlowPts.size(), largestNumPts);	
		
		//Add velocity lines
		this.velFunc  = new Scroll2DGraph("Uv", "Velocity (m/s)", 0, 1, largestNumPts);
		this.velFunc.setDisplayExtraXValues(true);
		this.velFunc.addGraphDataLine("vJustRight", Color.GREEN, Color.GREEN, vJustRightPts);
		this.velFunc.addGraphDataLine("vFast", Color.RED, Color.RED, vFastPts);
		this.velFunc.addGraphDataLine("vVeryFast", Color.MAGENTA, Color.MAGENTA, vVeryFastPts);
		this.velFunc.addGraphDataLine("vSlow", Color.BLUE, Color.BLUE, vSlowPts);
		this.velFunc.addGraphDataLine("vVerySlow", Color.YELLOW, Color.YELLOW, vVerySlowPts);
		
		// Obtain distance data points
		tempArray = FuzzySetsManager.getInstance().getQualifiedConsequent(FuzzySet.D_CLOSE, 1.0);
		tempLowerBound = FuzzySetsManager.getInstance().getLowerBound(FuzzySet.D_CLOSE);
		ArrayList<Point2D> dClosePts = this.buildPoints(tempArray, tempLowerBound);
		largestNumPts = dClosePts.size();
		
		tempArray = FuzzySetsManager.getInstance().getQualifiedConsequent(FuzzySet.D_FAR, 1.0);
		tempLowerBound = FuzzySetsManager.getInstance().getLowerBound(FuzzySet.D_FAR);
		ArrayList<Point2D> dFarPts = this.buildPoints(tempArray, tempLowerBound);
		largestNumPts = Math.max(dFarPts.size(), largestNumPts);
		
		tempArray = FuzzySetsManager.getInstance().getQualifiedConsequent(FuzzySet.D_JUSTRIGHT, 1.0);
		tempLowerBound = FuzzySetsManager.getInstance().getLowerBound(FuzzySet.D_JUSTRIGHT);
		ArrayList<Point2D> dJustRightPts = this.buildPoints(tempArray, tempLowerBound);
		largestNumPts = Math.max(dJustRightPts.size(), largestNumPts);
		
		tempArray = FuzzySetsManager.getInstance().getQualifiedConsequent(FuzzySet.D_VERYCLOSE, 1.0);
		tempLowerBound = FuzzySetsManager.getInstance().getLowerBound(FuzzySet.D_VERYCLOSE);
		ArrayList<Point2D> dVeryClosePts = this.buildPoints(tempArray, tempLowerBound);
		largestNumPts = Math.max(dVeryClosePts.size(), largestNumPts);
		
		tempArray = FuzzySetsManager.getInstance().getQualifiedConsequent(FuzzySet.D_VERYFAR, 1.0);
		tempLowerBound = FuzzySetsManager.getInstance().getLowerBound(FuzzySet.D_VERYFAR);
		ArrayList<Point2D> dVeryFarPts = this.buildPoints(tempArray, tempLowerBound);
		largestNumPts = Math.max(dVeryFarPts.size(), largestNumPts);
		
		// Add distance data lines
		this.disFunc = new Scroll2DGraph("Ud", "Distance (m)", 0, 1, largestNumPts);
		this.disFunc.setDisplayExtraXValues(true);
		this.disFunc.addGraphDataLine("dClose", Color.BLUE, Color.BLUE, dClosePts);
		this.disFunc.addGraphDataLine("dFar", Color.RED, Color.RED, dFarPts);
		this.disFunc.addGraphDataLine("dJustRight", Color.GREEN, Color.GREEN, dJustRightPts);
		this.disFunc.addGraphDataLine("dVeryClose", Color.YELLOW, Color.YELLOW, dVeryClosePts);
		this.disFunc.addGraphDataLine("dVeryFar", Color.MAGENTA, Color.MAGENTA, dVeryFarPts);
		
		this.establishLayout();
		this.validate();
	}
	
	
}
